using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using ConsoleFx;
using ConsoleFx.Programs.Simple;
using ConsoleFx.Validators;

using NConfigGenerator;

namespace NConfigGeneratorCLI
{
    internal static class Runner
    {
        private static string _language = "c#";
        private static string _namespace;
        private static string _className;
        private static string _propertyName = "Current";
        private static string _xmlFile;
        private static string _sourceFile;

        internal static int Run()
        {
            var app = new ConsoleProgram(Handler,
                includeHelpSupport: true);
            try
            {
                IEnumerable<string> validLanguages = (from c in CodeDomProvider.GetAllCompilerInfo()
                    where c.IsCodeDomProviderTypeValid
                    select c.GetLanguages()[0]);
                app.AddOption("language", "l", OptionRequirement.Optional, expectedParameters: 1)
                    .ValidateWith(new LookupValidator(validLanguages))
                    .AssignTo(() => _language);
                app.AddOption("namespace", "ns", OptionRequirement.Optional, expectedParameters: 1)
                    .ValidateWith(new StringValidator(1, int.MaxValue))
                    .AssignTo(() => _namespace);
                app.AddOption("class", "c", OptionRequirement.Optional, expectedParameters: 1)
                    .ValidateWith(new StringValidator(1, int.MaxValue))
                    .AssignTo(() => _className);
                app.AddOption("property", "p", OptionRequirement.Optional, expectedParameters: 1)
                    .ValidateWith(new StringValidator(1, int.MaxValue))
                    .AssignTo(() => _propertyName);

                app.AddArgument().ValidateWith(new PathValidator()).AssignTo(() => _xmlFile);
                app.AddArgument().AssignTo(() => _sourceFile);

                return app.Run();
            }
            catch (Exception ex)
            {
                return app.HandleError(ex);
            }
        }
        
        private static int Handler()
        {
            string xml = File.ReadAllText(_xmlFile);
            ConfigTree configTree = ConfigTree.InferFromXml(xml);
            var options = new GeneratorOptions {
                Language = _language,
                Namespace = _namespace,
                ConfigClassName = _className,
                ConfigPropertyName = _propertyName
            };
            string code = Generator.Generate(configTree, options);
            File.WriteAllText(_sourceFile, code);
            return 0;
        }
    }
}